package com.snap.vseries.ui;

import android.annotation.SuppressLint;
import android.app.Dialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;

import com.orhanobut.logger.Logger;
import com.snap.vseries.R;
import com.snap.vseries.base.BaseActivity;
import com.snap.vseries.bean.SerialPortDevice;
import com.snap.vseries.serial.Cmd;
import com.snap.vseries.serial.SerialPortHelper;
import com.snap.vseries.ui.widget.DialogView;
import com.snap.vseries.ui.widget.TextButton;
import com.snap.vseries.utils.DoubleUtils;
import com.snap.vseries.utils.ToastUtils;
import com.snap.vseries.utils.TopTitleUtils;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import butterknife.BindView;
import butterknife.BindViews;

import static com.snap.vseries.AppConfig.SERIAL_BAUD_RATE;
import static com.snap.vseries.AppConfig.SERIAL_PORT;
import static com.snap.vseries.AppConfig.TEMP_TYPE_COUNT;

public class PidSettingActivity extends BaseActivity {
    final String HELP_NUMBER = "100000";//读取Pid时用来辅助计算
    @BindView(R.id.save_setting_btn)
    protected TextButton saveSettingBtn;
    @BindView(R.id.read_setting_btn)
    protected TextButton readSettingBtn;
    @BindViews({R.id.tv_37_1, R.id.tv_37_2, R.id.tv_37_3})
    List<TextView> mTextViewList37;
    @BindViews({R.id.tv_55_1, R.id.tv_55_2, R.id.tv_55_3})
    List<TextView> mTextViewList55;
    @BindViews({R.id.tv_72_1, R.id.tv_72_2, R.id.tv_72_3})
    List<TextView> mTextViewList72;
    @BindViews({R.id.tv_95_1, R.id.tv_95_2, R.id.tv_95_3})
    List<TextView> mTextViewList95;
    List<List<TextView>> mTextViewList = new ArrayList<>();
    //四行三列（行，温度；列，PID）
    String[][] pidArr = new String[4][3];
    private ScheduledExecutorService executor;
    private StringBuffer beforeSaveContent;//保存前pid数据
    private WritePidAsyncTask writePidAsyncTask;
    private SerialPortHelper serialPortHelper;
    //读pid

    /**
     * 读温漂
     */

    public void onCallback(boolean isSuccess, byte[] data) {
        if (!isSuccess) {
            Logger.e("查询PID参数失败");
            return;
        }
        if (!Cmd.cmdValidate(data)) {
            Logger.e("查询PID参数：状态帧校验失败");
            return;
        }
        beforeSaveContent.setLength(0);
        if (data == null || data.length < 30) {
            return;
        }
        byte[] result = new byte[24];
        System.arraycopy(data, 7, result, 0, 24);
        for (int i = 0; i < pidArr.length; i++) {
            for (int j = 0; j < pidArr[0].length; j++) {
                int index = i * 6 + j * 2;
                float value = ((result[index] & 0xff) << 8) + (result[index + 1] & 0xff);
                DecimalFormat df = new DecimalFormat("0.00");
                String valueString = df.format(value / 100f);
                pidArr[i][j] = valueString;
            }
        }
        for (String[] strings : pidArr) {
            //每一行都有数据时才开始渲染
            if (TextUtils.isEmpty(strings[0])) {
                return;
            }
        }
        //全部有数据后再渲染UI
        runOnUiThread(() -> {
            for (int i = 0; i < mTextViewList.size(); i++) {
                for (int j = 0; j < mTextViewList.get(i).size(); j++) {
                    mTextViewList.get(i).get(j).setText(pidArr[i][j]);
                    beforeSaveContent.append(pidArr[i][j]);
                }
            }
        });
    }


    private Dialog dialog;


    @Override
    protected int layoutResId() {
        return R.layout.activity_pid_setting;
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        LogViewApi.bind(this);
        initViews();
        this.serialPortHelper = new SerialPortHelper(new SerialPortDevice(SERIAL_PORT, SERIAL_BAUD_RATE));
        this.executor = Executors.newScheduledThreadPool(1);

        try {
            executor.schedule(new ReadPidTask(), 0, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @SuppressLint("StaticFieldLeak")
    private void initViews() {
        new TopTitleUtils(this).setTitle("PID设置").setLeft(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
        initTextView();
        saveSettingBtn.setOnClickListener(v -> {
            if (contentIsChanged()) {
                //设置pid
                writePidAsyncTask = new WritePidAsyncTask("保存中...");
                writePidAsyncTask.execute();
            } else {
                Logger.i("PID设置，数据没有变化，无法更新！");
                ToastUtils.get().showText("数据没有变化，无法更新！");
            }
        });
        readSettingBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    executor.schedule(new ReadPidTask(), 0, TimeUnit.MILLISECONDS);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void initTextView() {
        mTextViewList.add(mTextViewList37);
        mTextViewList.add(mTextViewList55);
        mTextViewList.add(mTextViewList72);
        mTextViewList.add(mTextViewList95);
        for (int i = 0; i < mTextViewList.size(); i++) {
            for (int j = 0; j < mTextViewList.get(i).size(); j++) {
                TextView textView = mTextViewList.get(i).get(j);
                textView.setOnClickListener(v -> showDialog(v, textView.getText().toString()));
            }
        }
    }

    private void showDialog(View view, String text) {
        DialogView dialogView = new DialogView(this)
                .setTitle("请输入数值")
                .setContentType(false)
                .setEditContent(text)
                .setOnClickListener(content -> {
                    try {
                        Long.valueOf(DoubleUtils.replaceZero(DoubleUtils.mul(content, HELP_NUMBER)));
                    } catch (NumberFormatException e) {
                        ToastUtils.get().showText("输入的值不符合规范");
                        return;
                    }
                    if (Double.valueOf(content) < 0 || Double.valueOf(content) > 10) {
                        ToastUtils.get().showText("取值范围为：[0,10]");
                        return;
                    }

                    content = new DecimalFormat("0.#####").format(Double.valueOf(content));
                    for (int i = 0; i < mTextViewList.size(); i++) {
                        for (int j = 0; j < mTextViewList.get(i).size(); j++) {
                            if (view.getId() == mTextViewList.get(i).get(j).getId()) {
                                mTextViewList.get(i).get(j).setText(content);
                                return;
                            }
                        }
                    }
                });
        dialogView.show();
    }

    /**
     * 对pid进行处理,保留5位小数
     */
    private String dealPid(String pid) {
        return DoubleUtils.roundByScale(DoubleUtils.replaceZero(pid), 5);
    }

    @Override
    protected void onDestroy() {
        if (writePidAsyncTask != null) {
            writePidAsyncTask.cancel(true);
        }
        super.onDestroy();
    }

    /**
     * 内容是否有变化
     */
    private boolean contentIsChanged() {
        StringBuffer finalContent = new StringBuffer();
        for (int i = 0; i < mTextViewList.size(); i++) {
            for (int j = 0; j < mTextViewList.get(i).size(); j++) {
                finalContent.append(mTextViewList.get(i).get(j).getText().toString());
            }
        }
        return !beforeSaveContent.toString().equals(finalContent.toString());
    }

    public void showLoading(String content) {
        if (dialog == null) {
            dialog = new Dialog(this, R.style.DimDialogStyle);
            dialog.setContentView(R.layout.dialog_loading);
            dialog.setCanceledOnTouchOutside(true);
            dialog.setCancelable(true);
        }
        TextView contentTv = dialog.findViewById(R.id.content_tv);
        contentTv.setText(content);
        dialog.show();
    }

    public void dismissLoading() {
        if (dialog != null) {
            dialog.dismiss();
        }
    }

    /**
     * 读取pid任务
     */
    private class ReadPidTask implements Runnable {
        @Override
        public void run() {
            try {
                beforeSaveContent = new StringBuffer();
                byte[] cmd = Cmd.queryPID(1);
                serialPortHelper.open();//打开串口
                Bundle bundle = serialPortHelper.execute(cmd);
                boolean isSuc = bundle.getBoolean("suc");
                byte[] data = bundle.getByteArray("data");
                onCallback(isSuc, data);
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            } finally {
                serialPortHelper.close();
            }
        }
    }

    /**
     * 写pid任务
     */
    @SuppressLint("StaticFieldLeak")
    class WritePidAsyncTask extends AsyncTask<Void, Void, Boolean> {
        private String loadingText;

        WritePidAsyncTask(String loadingText) {
            this.loadingText = loadingText;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            showLoading(loadingText);
        }

        @SuppressLint("WrongThread")
        @Override
        protected Boolean doInBackground(Void... voids) {
            try {
                float[] params = new float[12];
                for (int i = 0; i < mTextViewList.size(); i++) {
                    for (int j = 0; j < mTextViewList.get(i).size(); j++) {
                        params[i * 3 + j] = Float.valueOf(mTextViewList.get(i).get(j).getText().toString());
                    }
                }
                serialPortHelper.open();//打开串口
                Bundle bundle = serialPortHelper.execute(Cmd.setPid(1, params));
                boolean isSuc = bundle.getBoolean("suc");
                if (isSuc) {
                    byte[] data = bundle.getByteArray("data");
                    if (Cmd.cmdValidate(data)) {
                        Logger.e(" 设置PID成功");
                        return true;
                    } else {
                        Logger.e(TEMP_TYPE_COUNT + " 设置PID失败");
                        return false;
                    }
                } else {
                    Logger.e(TEMP_TYPE_COUNT + " 设置PID失败");
                    return false;
                }
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
                return false;
            } finally {
                serialPortHelper.close();
            }
        }

        @Override
        protected void onPostExecute(Boolean result) {
            dismissLoading();
            if (result) {
                ToastUtils.get().showText("保存成功");
            } else {
                ToastUtils.get().showText("保存失败");
            }
        }
    }
}
